package org.mayuanxiaonong.timserver.handler.deliver;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.mayuanxiaonong.timserver.packet.Packet;

/**
 * 抽象报文分发器
 * 
 * @author 9527
 *
 * @param <V>
 */
public abstract class Deliver<V> implements Runnable {

	private static ExecutorService executor = Executors.newCachedThreadPool();

	private BlockingQueue<Packet> queue = null;
	private int times;

	public V result;

	public Deliver(BlockingQueue<Packet> queue, int times) {
		this.queue = queue;
		this.times = times;
	}

	@Override
	public void run() {
		while (true) {
			Packet packet = null;
			try {
				packet = queue.poll(5, TimeUnit.SECONDS);
			} catch (InterruptedException e) {
			}
			if (packet == null) {
				break;
			}
			handle(packet);
		}
	}

	/**
	 * 处理报文
	 * 
	 * @param packet
	 */
	private void handle(final Packet packet) {
		boolean isSuccess = false;
		int n = 0;

		while (!isSuccess && n < times) {
			Future<V> future = executor.submit(new CallTask(packet));

			// 得到处理结果，用于判断是否成功以及后续处理
			try {
				result = future.get();
			} catch (InterruptedException | ExecutionException e) {
			}

			isSuccess = isSuccess();
			if (!isSuccess) {
				n++;
			}
		}

		if (isSuccess) {
			onSuccess();
		} else {
			onFailure();
		}
	}

	class CallTask implements Callable<V> {
		Packet packet = null;

		CallTask(Packet packet) {
			this.packet = packet;
		}

		@Override
		public V call() throws Exception {
			return handle0(packet);
		}
	};

	/**
	 * 真正的报文分发业务逻辑实现
	 * 
	 * <pre>
	 * At 2015-06-11 23:00:01
	 * By 码园小农
	 * Description 此处为真正的业务逻辑处理，不完全是分发消息，改为handle。
	 * 
	 * @return
	 */
	public abstract V handle0(Packet packet);

	/**
	 * 判断分发是否成功,各种分发器根据特定逻辑判断并返回
	 * 
	 * @return
	 */
	public abstract boolean isSuccess();

	/**
	 * 成功处理逻辑
	 */
	public abstract void onSuccess();

	/**
	 * 失败处理逻辑
	 */
	public abstract void onFailure();
}